const puppeteer = require("puppeteer");
const {TimeoutError} = puppeteer.errors;
const axios = require("axios");
const qs = require("qs");

class WxRobotAuth {
    constructor() {
        // this.key = "89D06C7A5EDA1F87A9398F2F5FA0091AB6A8D6D7"; // han
        this.key = "889FC5B25AEDABDDBBA25A67CE7420C330DFF535"; //hulk
        // this.key = "771BBB673A0C3DABE8D6215DE6825F621D5A3780";
        this.host = "http://8.140.155.52:8203"
        this.loginUrl = this.host + "/tmp/wxext/www/wxext-master/docs/home/auth_ls.html?key=" + this.key;
        this.userCenterUrl = this.host + "/api?json&key=" + this.key;

        this.browser = null;
        this.page = null;

        this.isTest = true;
        /**
         * 进入http://127.0.0.1:8203/tmp/wxext/www/wxext-master/docs/home/i.html
         * 个人中心页面代码审查查看key值
         */
    }

    /**
     * 重复刷新，手动创造请求频繁
     * @returns {Promise<void>}
     */
    async createTimeout() {
        while (1) {
            await this.page.click("#adfortest_plugin_refresh");
            await this.page.waitForTimeout(1000);
            var temp = await this.page.evaluate(() => {
                return document.querySelector("#adfortest_plugin_title span").innerText;
            })
            if (temp.includes("您请求太频繁")) {
                break
            }
        }

    }

    /**
     * 多次失败后用于检查是否出现请求太频繁
     * @returns {Promise<boolean>}
     */
    async checkIsBusy() {
        var temp = await this.page.evaluate(() => {
            return document.querySelector("#adfortest_plugin_title span").innerText;
        })
        if (temp.includes("您请求太频繁")) {
            return true;
        }
        return false;
    }

    /**
     * 当出现繁忙时刷新直到不再繁忙
     * @returns {Promise<void>}
     */
    async refreshAdforTestPlugin() {
        while (1) {
            await this.page.click("#adfortest_plugin_refresh");
            await this.page.waitForTimeout(1000);
            if (!await this.checkIsBusy()) {
                console.log("不再繁忙了，可以猜了")
                this.exitAwaitTime += 2;
                break
            } else {
                console.log("达到限制，等待刷新....");
            }
        }

    }

    /**
     * 初始点击的时候判断是否太频繁
     * */
    async awaitCheckBusy(needAwait) {
        if (needAwait) {
            await this.page.waitForTimeout(1000 * 2);
        }
        var isBusy = await this.checkIsBusy();
        if (isBusy) {
            console.log("达到限制，等待刷新....");
            await this.refreshAdforTestPlugin();
        }
    }

    /**
     * 点击按钮自动授权
     * @returns {Promise<void>}
     */
    async clickBtn() {
        await this.awaitCheckBusy(true);
        await this.page.waitForSelector("#adfortest_plugin_ask .vd_ckbox", {timeout: 5000});
        await this.page.click("#adfortest_plugin_ask .vd_ckbox:nth-of-type(2)");
        await this.page.waitForTimeout(1000);
        const isHide = await this.page.evaluate(() => {
            return document.querySelector("#adfortest_plugin").style.display == "none";
        })
        // await this.createTimeout(page);
        if (!isHide) {
            await this.awaitCheckBusy(false);
            await this.page.waitForTimeout(1000);
            console.log("验证失败！！！")
            await this.clickBtn();
        } else {
            console.log("验证成功！！！")

        }
    }

    /**
     * 检查授权是否成功
     */
    async checkIsSuccess(wxid) {
        const userData = await this.getUserData();
        console.log("开始检查授权是否成功! ")
        if (userData && userData.hasOwnProperty("data") && userData.data.length > 0) {
            const currentUser = userData.data.filter((item) => {
                return item.wxid == wxid
            })
            console.log(JSON.stringify(currentUser))
            if (currentUser.length == 0) {
                throw new Error("当前用户不存在！")
            }
            const authData = currentUser[0]
            const authTime = new Date(authData.authTime);
            const nowTime = new Date();
            if (authTime > new Date(nowTime.setHours(nowTime.getHours() + 20))) {
                console.log("授权成功！")
                return true;
            }
        }
        console.log("授权失败，等待重新授权! ")
        return false;
    }

    /**
     * 等待某个窗口出现或者隐藏
     * loadingoverlay
     * */
    async checkLoading(sel, options) {
        await this.page.waitForSelector(sel, options);
    }

    /**
     * 改变下拉框的值
     * */
    async changeSelect(sel, val) {
        await this.page.select(sel, val);
    }


    /**
     * 获取授权主函数
     */
    async getAuth(wxid) {
        try {
            await this.page.goto(this.loginUrl, {waitUntil: "networkidle2"});
            await this.page.waitForTimeout(2000);
            await this.page.goto(this.loginUrl, {waitUntil: "networkidle2"});
            await this.page.waitForSelector("#show", {timeout: 0});

            await this.changeSelect("#select_wxid", wxid)
            await this.page.click("#show");
            await this.clickBtn();
            // loadingoverlay
            await this.checkLoading(".loadingoverlay", {hidden: true});

            if (!await this.checkIsSuccess(wxid)) {
                await this.page.waitForTimeout(1000);
                console.log("授权失败，开始刷新页面重新授权！")
                await this.getAuth(wxid);
            }
        } catch (e) {
            if (e instanceof TimeoutError) {
                await this.waitForTimeout(1000 * 5);
            }
            if (e.toString().includes("当前用户不存在")) {
                return
            }
            await this.waitForTimeout(1000);
            console.log("激活报错！" + e.toString());
            console.log("授权出错，开始刷新页面重新授权！")
            await this.getAuth(wxid);
        }

    }

    /**
     * 获取用户授权数据
     */
    async getUserData() {
        const {data: userData} = await axios({
            method: 'post',
            url: this.userCenterUrl,
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            data: qs.stringify({method: "list"})
        })
        return userData;
    }

    async init(index = 0) {
        const options = {
            headless: false,
            product: "chrome",
            slowMo: 30,
            timeout: 20000,
            args: [
                "--ignore-certificate-errors",
                "--no-sandbox",
                "--disable-gpu"
            ],
        }
        if (this.isTest) {
            options["executablePath"] = "chromedriver\\chrome.exe"
        }
        this.browser = await puppeteer.launch(options)
        console.log("授权url: " + this.loginUrl);
        console.log("-------------------------------------")
        try {
            const userData = await this.getUserData();
            console.log("用户数据: " + JSON.stringify(userData));
            console.log("-------------------------------------")
            if (userData && userData.hasOwnProperty("method") && userData.method === "list_Recv" && userData.count >= 1) {
                const filterData = userData.data.filter(item => item.isLogin === 1);
                if (filterData === 0) {
                    throw new Error("微信未在127.0.0.1:8203中连接");
                }
                for (var i = 0; i < userData.data.length; i++) {
                    this.page = await this.browser.newPage();
                    var wxid = userData.data[i].wxid;
                    console.log("微信名称：" + userData.data[i].nickName + " wxid: " + wxid);
                    await this.getAuth(wxid);
                    await this.page.waitForTimeout(1000 * 2);
                    this.page.close();
                }

            } else {
                throw new Error("获取用户授权列表异常" + JSON.stringify(userData))
            }

        } catch (e) {

        } finally {
            await this.page.waitForTimeout(1000 * 5);
            if (this.browser != null && !this.browser.closed) {
                this.browser.close()
            }
        }
    }


}


// module.exports = {
//     WxRobotAuth
// }
new WxRobotAuth().init()
